package com.student.education.aop;


import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * spring的aop方法 通过前置通知 后置通知 环绕通知将日志打印出来
 */
@Component
@Aspect
@Slf4j
public class WebAopLog {

    String className = null;

    /**
     * 切点
     */
    @Pointcut("execution(public * com.student.education.service..*.*(..)))")
    public void log() {
    }

    /**
     * 前置通知打印事件
     * @param joinPoint
     */
    @Before(value = "log()")
    public void before(JoinPoint joinPoint) {
        className = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        StringBuilder logger = new StringBuilder();
        logger.append("\n");
        logger.append("┏━━━━━━━━━━━" + className + "━━━━━━━━━━━━━━━━\n").append("┣ 方法：" + methodName + "\n").append("┣ 入参：");
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if(arg instanceof StandardMultipartHttpServletRequest || arg instanceof HttpServletRequest|| arg instanceof HttpServletResponse) {
                continue;
            }
            logger.append(JSON.toJSON(arg));
        }
        logger.append("\n").append("┗━━━━━━━━━━━" + className + "━━━━━━━━━━━━━━━━\n");
        log.info("\n" + logger.toString());
    }

    /**
     * 后置通知打印事件
     * @param returnObj
     */
    @AfterReturning(value = "log()", returning = "returnObj")
    public void afterReturn(Object returnObj) {
        StringBuilder logger = new StringBuilder();
        logger.append("\n").append("┏━━━").append(className).append("━━━━━━━━━━━━━━━━\n").append("┣ 出参：").append(JSON.toJSON(returnObj)).append("\n").append("┗━━━━━━━━━━━").append(className).append("━━━━━━━━━━━━━━━━\n");
        log.info("\n" + logger.toString());
    }

    /**
     * 前置异常通知
     * @param e
     */
    @AfterThrowing(value = "execution(public * com.student.education.service..*.*(..)))", throwing = "e")
    public void afterThrowing(Throwable e) {
        log.error("afterThrowing: " + e.getMessage(), e);
    }

    /**
     * 环绕通知
     * @param proceedingJoinPoint
     * @return
     * @throws Throwable
     */
    @Around(value = "log()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Long begin = System.currentTimeMillis();
        StringBuilder logger = new StringBuilder("around: ");
        Object result = null;
        try {
            result = proceedingJoinPoint.proceed();
        } catch (Exception e) {
            log.error(logger + e.getMessage(), e);
        }
        Long end = System.currentTimeMillis();
        logger.append(" 执行时间: ").append(end - begin).append("ms");
        log.info("\n" + logger.toString());
        return result;
    }
}
